home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS11.ADF
/
C
/
VidTex.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-08-05
|
14KB
|
357 lines
/*
* Vidtex version 1.0
* by George Musser Jr.
* CIS 76566,3714
* 25 May 1986
*
* This program displays a medium or high resolution Vidtex picture
* downloaded from CompuServe. The program tries to scale the picture
* to fit the current window size; the smaller the window, the more
* information the algorithm must discard to squeeze the picture.
*
* CLI syntax: VIDTEX <file>
* Workbench: Select both picture file and VIDTEX
*
*/
#include <exec/types.h>
#include <intuition/intuition.h>
#include <workbench/startup.h>
#include <stdio.h>
/* ===== Vidtex definitions ============================================= */
#define MED_X 128 /* Picture elements in medium resolution */
#define MED_Y 96
#define HI_X 256 /* Picture elements in high resolution */
#define HI_Y 192
#define ZERO ' ' /* Vidtex code for 0 pixels */
#define SEQLEN 3 /* Length of escape sequences */
#define MED_RES "\x1BGM" /* Sequence for medium resolution */
#define HI_RES "\x1BGH" /* Sequence for high resolution */
#define ESC 0x1B /* Escape character */
/* ===== Window definitions ============================================= */
#define MIN_WIDTH 50 /* Smallest window size */
#define MIN_HEIGHT 25
#define MAX_WIDTH 640 /* Largest window size */
#define MAX_HEIGHT 200
#define HI_WIDTH MAX_WIDTH /* Initial window size */
#define MED_WIDTH 375 /* 2.5*(MED_X+BorderLeft+BorderRight) */
#define HI_HEIGHT MAX_HEIGHT
#define MED_HEIGHT 109 /* MED_Y+BorderTop+BorderBottom */
#define BACK 0 /* Background color */
#define FORE 1 /* Foreground color */
#define ERRCODE 20 /* Return code in case of trouble */
/* ----- The generic OpenLibrary() call ----- */
#define OPENLIB(p,l) (struct p *)OpenLibrary(l,LIBRARY_VERSION)
/* ===== Global variables =============================================== */
struct NewWindow NewWindow = /* Our output window */
{
0,0, /* Upper left corner */
HI_WIDTH,HI_HEIGHT, /* Width and height */
-1,-1, /* Use Wbench's detail and block pens */
CLOSEWINDOW | NEWSIZE, /* Ye olde IDCMP */
WINDOWDEPTH | WINDOWCLOSE /* Depth, close... */
| WINDOWDRAG | WINDOWSIZING /* ...drag, and sizing gadgets */
| SMART_REFRESH, /* Let Intuition handle refreshing */
NULL, /* No gadgets */
NULL, /* Or images */
"", /* We'll get the title later */
NULL, /* Use Workbench screen */
NULL, /* No bitmap */
MIN_WIDTH,MIN_HEIGHT, /* Smallest size */
MAX_WIDTH,0, /* Largest size */
WBENCHSCREEN /* Standard screen */
};
/* N.B. You can't scale vertically; I couldn't get that to work well */
/* ----- These guys are used in main() and Abort() ----- */
LONG olddir = NULL; /* Lock on former directory */
FILE *Fp = NULL; /* File pointer */
struct IntuitionBase *IntuitionBase = NULL; /* Intuition pointer */
struct GfxBase *GfxBase = NULL; /* Graphics pointer */
struct Window *Window = NULL; /* Pointer to our window */
/* ----- These make the program easier to read ----- */
#define ARG WBenchMsg->sm_ArgList
#define RPORT Window->RPort /* Window's RastPort */
#define UPORT Window->UserPort /* Here's the user message port */
#define LEFT Window->BorderLeft /* Offsets into window area */
#define TOP Window->BorderTop
#define RIGHT (Window->Width - Window->BorderRight - 1)
#define BOTTOM (Window->Height - Window->BorderBottom)
#define WIDTH (RIGHT - LEFT)
#define HEIGHT (BOTTOM - TOP)
/* ===== main() ======================================================== */
main(argc,argv)
int argc;
char *argv[];
{
void Abort(); /* Error handler */
struct IntuiMessage *GetMsg(); /* Message retrieval */
/* ===== Local variables ============================================= */
extern struct WBStartup *WBenchMsg; /* Startup message from Workbench */
char *name; /* Name of file to open */
register char Buffer[SEQLEN]; /* Input buffer when scanning */
register int Max_x = HI_X; /* Width (for wrap-around) */
register int Max_y = HI_Y; /* Height (for bounds checking) */
long Pos; /* File position of picture */
register int color; /* Current color */
float xFactor,yFactor; /* Scaling factors for picture */
float x,y; /* Position in picture */
register char ch; /* Single character from file */
register int New_y,Old_y; /* Coordinates in window */
register struct IntuiMessage *message; /* IDCMP message */
ULONG class; /* Message class */
/* ===== Open up file ================================================ */
if (argc == 0) /* Looks like we were called from Workbench */
if (WBenchMsg->sm_NumArgs > 1) /* Did user select a project? */
if ((++ARG)->wa_Lock) { /* Yup, but is lock OK? */
olddir = CurrentDir(ARG->wa_Lock); /* Lock current dir */
name = (ARG--)->wa_Name; /* Get filename */
} /* (++ and -- select second argument) */
else
Abort ("Can't lock directory");
else
Abort ("Please select a project");
else if (argc == 1) /* Oops, user forgot filename */
Abort ("Please specify a filename");
else /* Got a filename */
name = argv[1];
if ((Fp = fopen(name,"r")) == NULL) /* Try to open file */
Abort ("Can't open file");
/* ===== Search for picture ========================================== */
strncpy (Buffer," ",SEQLEN);
while (strncmp(Buffer,MED_RES,SEQLEN) && strncmp(Buffer,HI_RES,SEQLEN)
&& NOT feof(Fp)) {
Buffer[0] = Buffer[1]; /* Buffer holds last three characters */
Buffer[1] = Buffer[2]; /* Shift buffer down... */
Buffer[2] = getc(Fp); /* ...so we can grab another character */
}
if (feof(Fp)) /* File is worthless */
Abort ("Can't find start of picture");
Pos = ftell(Fp); /* Save position */
/* ===== Open up libraries =========================================== */
if ((IntuitionBase = OPENLIB(IntuitionBase,"intuition.library")) == NULL)
Abort ("Can't open Intuition Library");
if ((GfxBase = OPENLIB(GfxBase,"graphics.library")) == NULL)
Abort ("Can't open Graphics Library");
/* ===== Open up window ============================================== */
if (NOT strncmp(Buffer,MED_RES,SEQLEN)) { /* Medium resolution? */
NewWindow.Width = MED_WIDTH; /* If so, adjust window size */
NewWindow.Height = MED_HEIGHT;
Max_x = MED_X; /* ...and picture size */
Max_y = MED_Y;
}
NewWindow.Title = argv[1]; /* Set window title to filename */
/* Now it's time to try opening the window */
if ((Window = (struct Window *)OpenWindow(&NewWindow)) == NULL)
Abort ("Can't open window");
/* ===== Get ready to show picture =================================== */
do { /* We may have to redraw this */
if (fseek(Fp,Pos,0)) /* Go to start of picture */
Abort ("Fseek woes");
xFactor = (float)WIDTH / Max_x; /* Scale to fit */
yFactor = (float)HEIGHT / Max_y; /* window snugly */
color = FORE; /* This flips to BACK initially */
x = (float)LEFT;
y = (float)TOP;
New_y = TOP;
SetAPen (RPORT,BACK); /* Clear window */
RectFill (RPORT,LEFT,TOP,RIGHT,BOTTOM);
Move (RPORT,LEFT,TOP); /* Start in upper left corner */
/* ===== Go for it ================================================ */
while (NOT feof(Fp) && (message = GetMsg(UPORT)) == NULL) {
SetAPen (RPORT,(color = (color == FORE) ? BACK : FORE));
/* This do-while loop gathers all the consecutive segments
* for the current color.
*/
do {
/* Specs say we've got to watch out for cursor movement */
while ((ch = getc(Fp)) == ESC) /* Cursor movement? */
switch (getc(Fp)) { /* Yup... */
case 'D' : /* Left */
x -= xFactor;
if (x >= LEFT) break;
x += WIDTH;
case 'A' : /* Up */
y -= yFactor;
if (y < TOP) y += HEIGHT;
break;
case 'C' : /* Right */
x += xFactor;
if (x <= RIGHT) break;
x -= WIDTH;
case 'B' : /* Down */
y += yFactor;
if (y > BOTTOM) y -= HEIGHT;
break;
case 'H' : /* Home */
x = (float)LEFT;
y = (float)TOP;
break;
case 'Y' : /* <lin><col> positioning */
/* Control characters are invalid */
if ((ch = getc(Fp)) < ZERO) ch = ZERO;
/* Assume line 1 corresponds to y=0 */
y = (float)(TOP + ch - ZERO);
if ((ch = getc(Fp)) < ZERO) ch = ZERO;
x = (float)(LEFT + getc(Fp) - ZERO);
break;
}
if (ch < ZERO) {
ch = NULL; /* We don't recognize this character... */
break; /* ...so give it up */
}
/* Not an escape sequence, so assume it's a run-length code */
else if ((x += (ch - ZERO)*xFactor) > RIGHT) {
y += yFactor;
x -= WIDTH;
}
} while ((ch = getc(Fp)) == ZERO);
if (ch == NULL) /* Don't understand this one... */
break; /* ...so we're done */
else {
ungetc (ch,Fp); /* Last character belongs to next color */
Old_y = New_y; /* Previous position in window */
New_y = Round(y); /* New position */
}
/* Don't bother drawing if we're going to be overwritten */
if (New_y == Round(y + yFactor))
Move (RPORT,Round(x),New_y); /* Move pen along */
else {
if (New_y > Old_y) { /* More than one line to draw? */
Draw (RPORT,RIGHT,Old_y); /* Yep, so finish out this line */
if (New_y > BOTTOM) { /* ...finish screen if appropriate */
RectFill (RPORT,LEFT,Old_y + 1,RIGHT,BOTTOM);
break;
}
if (New_y - Old_y > 1) /* ...fill intermediate area */
RectFill (RPORT,LEFT,Old_y + 1,RIGHT,New_y - 1);
Move (RPORT,LEFT,New_y); /* ...and move to the new line */
}
Draw (RPORT,Round(x),New_y); /* Draw line to new position */
}
if (Chk_Abort()) Abort (""); /* Abort if user so chooses */
} /* while */
/* When you size the window and then leave the mouse perfectly still,
* Wait() and GetMsg() return with message == NULL. So I put the
* two statements into a while loop.
*/
while (message == NULL) { /* Do we have a message? */
Wait (1 << UPORT->mp_SigBit); /* No, so sleep 'til we get one */
message = GetMsg(UPORT);
}
class = message->Class; /* What sort of message? */
ReplyMsg (message); /* Reply */
} while (class != CLOSEWINDOW); /* Continue until done */
Abort (""); /* We're outta here */
}
/* ===== Round() ========================================================
*
* Round() rounds a positive float to the nearest whole number. Could be
* a macro, but that would involve four calculations of the expression.
*
*/
int Round(x)
float x;
{
return ( ((x) - (int)(x) < 0.5) ? (int)(x) : (int)(x) + 1 );
}
/* ===== Abort() ========================================================
*
* Abort() closes resources and returns the appropriate error code.
*
*/
void Abort (Msg)
char *Msg; /* Error message */
{
if (olddir) CurrentDir (olddir);
if (Fp) fclose (Fp);
if (IntuitionBase) CloseLibrary (IntuitionBase);
if (GfxBase) CloseLibrary (GfxBase);
if (Window) CloseWindow (Window);
if (stclen(Msg)) {
fprintf (stderr,"%s.\n",Msg);
exit (ERRCODE);
}
else exit (0);
}